home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mush-7.1.1 / viewopts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-02  |  17.9 KB  |  575 lines

  1. /* @(#)viewopts.c    (c) copyright    10/18/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. struct viewopts {
  6.     char *v_opt;
  7.     char *v_prompt;
  8.     char *v_description;
  9. #ifdef SUNTOOL
  10.     Panel_item v_choice;
  11.     Panel_item v_text;
  12. #endif /* SUNTOOL */
  13. };
  14.  
  15. #ifdef SUNTOOL
  16. short dat_cycle_cursor[] = {
  17.     0x07C0, 0x0FE0, 0x1834, 0x301C, 0x601C, 0x203C, 0x0000, 0x0000,
  18.     0x7808, 0x700C, 0x7018, 0x5830, 0x0FE0, 0x07C0, 0x0000, 0x0000
  19.  
  20. };
  21. mpr_static(cycle,           16, 16, 1, dat_cycle_cursor);
  22. #endif /* SUNTOOL */
  23.  
  24. /*
  25.  * struct contains the option, a prompt if it has a string value, whether
  26.  * or not it applies to non suntools, line mode, or both, and a
  27.  * string describing what the option does. If the prompt string starts
  28.  * with a minus sign, then the value can be set without a value. This
  29.  * is there to indicate to option_line to print a toggle (cycle) pixrect
  30.  * and to print TRUE/FALSE telling whether the value is on or off regardless
  31.  * of it's "string" value.
  32.  */
  33. struct viewopts viewopts[] = {
  34.     { "alwaysignore", NULL,
  35.     "Always ignore the message headers on the 'ignored' list." },
  36.     { "ask", NULL,
  37.     "Prompts for a subject on outgoing mail." },
  38.     { "askcc", NULL,
  39.     "Ask for list of Carbon Copy recipients whenever sending mail." },
  40.     { "autodelete", NULL,
  41.     "Automatically delete ALL READ messages whenever you update mail." },
  42.     { "autoedit", NULL,
  43.     "Automatically enter editor for REPLIES only (not toolmode)." },
  44.     { "autoinclude", NULL,
  45.     "Include a copy of author's message each time you reply to mail." },
  46.     { "autoprint", NULL,
  47.     "Display the next message on the list when you delete a message." },
  48.     { "auto_route", "-Host/Path:",
  49.     "Remove redundant uucp addresses when replying to messages." },
  50.     { "autosign", "-Filename:",
  51.     "Add file (~/.signature if set but no value) at end of all letters." },
  52.     { "autosign2", "Addr:File:",
  53.     "Signature to use for specific addresses. \"addr, ... : <signature>\""},
  54.     { "cdpath", "Path:",
  55.     "Path to search for directories when the \"cd\" command is issued." },
  56.     { "cmd_help", "Path:",
  57.     "Location of the general help file for line and curses modes." },
  58.     { "complete", "Character:",
  59.     "The character typed to cause a word completion to occur." },
  60.     { "crt", "Lines:",
  61.     "The number of lines a message must have for 'pager' to be invoked." },
  62.     { "crt_win", "Lines:",
  63.     "Lines in the tool mode text subwindow for paging messages." },
  64.     { "curses_help", "-Commands:",
  65.     "List of curses commands whose bindings appear in the help display." },
  66.     { "date_received", NULL,
  67.     "Time displayed for message headers shows date received (or sent)." },
  68.     { "dead", "Filename:",
  69.     "The name of the file to store dead mail (default = ~/dead.letter)." },
  70.     { "domain_route", "-Host/Path:",
  71.     "Cause short-circuiting of domain addresses when auto-routing." },
  72.     { "dot", NULL,
  73.     "Allow \".\" on a line by itself to send letter." },
  74.     { "edit_hdrs", NULL,
  75.     "Allow headers of messages to be edited using your editor." },
  76.     { "editor", "Editor:",
  77.     "Editor for message editing (default = env EDITOR or \"vi\")." },
  78.     { "escape", "Character:",
  79.     "Escape character for extended editing commands (default = ~)." },
  80.     { "fignore", "Patterns:",
  81.     "Filename extensions or patterns ignored in completions." },
  82.     { "folder", "Pathname:",
  83.     "Full pathname to the directory where personal folders are kept." },
  84.     { "fortune", "-Flag:",
  85.     "Add fortune to end of letters.  Flag to \"fortune\" is optional." },
  86.     { "fortunates", "Users:",
  87.     "Those who will receive fortunes if fortune is set (default: All)." },
  88.     { "hdr_format", "Format:",
  89.     "Formatting string for headers.  \"headers -?\" or help hdr_format." },
  90.     { "history", "Number:",
  91.     "How many commands to remember (like csh)." },
  92.     { "hold", NULL,
  93.     "Read but not deleted messages are saved in spool -- not mbox." },
  94.     { "home", "Directory:",
  95.     "The user's home directory." },
  96.     { "hostname", "Hostname:",
  97.     "User-definable name for the name of your machine." },
  98.     { "ignore_bang", NULL,
  99.     "Ignore '!' as a history reference.  Otherwise, escape by: \\!" },
  100.     { "ignoreeof", "-Command:",
  101.     "Ignores ^D as exit, or (if set), execute \"command\"." },
  102.     { "indent_str", "String:",
  103.     "String to offset included messages within your letters." },
  104.     { "in_reply_to", "-String:",
  105.     "When responding to mail, add In-Reply-To: to message headers." },
  106.     { "keepsave", NULL,
  107.     "Prevents messages from being marked as `deleted' when you `save'." },
  108.     { "known_hosts", "Host list:",
  109.     "List of hosts that your site is known to uucp mail to." },
  110.     { "logfile", "Filename:",
  111.     "Log outgoing mail headers only.  Message text not logged." },
  112.     { "mail_icon", "Filename:",
  113.     "Alternate pixmap to use when tool is closed to an icon." },
  114.     { "mbox", "Filename:",
  115.     "Filename to use instead of ~/mbox for default mailbox." },
  116.     { "metoo", NULL,
  117.     "When replying to mail, metoo preserves your name on mailing list." },
  118.     { "mil_time", NULL,
  119.     "24-hour military time format is used whenever a time is printed." },
  120.     { "msg_win", "Lines:",
  121.     "Number of lines in the message composition window for tool mode." },
  122.     { "newline", "-Command:",
  123.     "Ignore RETURN.  If set to a command, execute that command." },
  124.     { "newmail_icon", "Filename:",
  125.     "Alternate icon shown when new mail is available." },
  126.     { "no_expand", NULL,
  127.     "Prevents expansion of Mush aliases in outgoing mail headers." },
  128.     { "no_hdrs", NULL,
  129.     "If set, personalized headers are NOT inserted to outgoing mail." },
  130.     { "no_reverse", NULL,
  131.     "Disables reverse video in curses mode -- uses \"bold\" in tool mode."},
  132.     { "nonobang", NULL,
  133.     "Suppresses errors from unsuccessful history references." },
  134.     { "nosave", NULL,
  135.     "Prevents aborted mail from being saved in $dead." },
  136.     { "output", NULL,
  137.     "The message list produced as output of the last command." },
  138.     { "pager", "Program:",
  139.     "Program name to be used as a pager for messages longer than crt." },
  140.     { "pre_indent_str", "String:",
  141.     "String to precede message text interpolated into message body." },
  142.     { "post_indent_str", "String:",
  143.     "String to succeed message text interpolated into message body." },
  144.     { "print_cmd", "Program:",
  145.     "Alternate program to use to send messages to the printer." },
  146.     { "printer", "Printer:",
  147.     "Printer to send messages to (default = environment PRINTER)." },
  148.     { "prompt", "String:",
  149.     "Your prompt.  \"help prompt\" for more information." },
  150.     { "quiet", "-Conditions:",
  151.     "Turn off verbose messages and error bells in various conditions." },
  152.     { "realname", "Name:",
  153.     "Your real name." },
  154.     { "record", "Filename:",
  155.     "Save all outgoing mail in specified filename." },
  156.     { "reply_to_hdr", "Headers:",
  157.     "List of headers use to construct reply addresses from a message." },
  158.     { "save_empty", NULL,
  159.     "Folders which have all messages deleted are NOT removed on updates." },
  160.     { "screen", "# of Headers:",
  161.     "Number of headers to print in non-suntools (text) mode." },
  162.     { "screen_win", "# of Headers:",
  163.     "Set the size of the header window for the tool mode only." },
  164.     { "show_deleted", NULL,
  165.     "Show deleted messages in headers listings (unused in curses mode)." },
  166.     { "show_hdrs", "Headers:",
  167.     "When displaying a message, show list of \"headers\" only." },
  168.     { "sendmail", "Program:",
  169.     "Program to use to deliver mail instead of using the default."},
  170.     { "sort", "-Option:",
  171.     "Pre-sorting of messages on mush startup (set to valid sort option)." },
  172.     { "squeeze", NULL,
  173.     "When reading messages, squeeze all blank lines into one." },
  174.     { "status", NULL,
  175.     "The success or failure status of the most recent command." },
  176.     { "thisfolder", "Folder:",
  177.     "This read-only variable gives the current folder name." },
  178.     { "tool_help", "Path:",
  179.     "Location of the help file for tool mode."  },
  180.     { "toplines", "Lines:",
  181.     "Number of lines to print of a message for the 'top' command."  },
  182.     { "tmpdir", "Directory:",
  183.     "Directory to use for temporary files used by Mush." },
  184.     { "unix", NULL,
  185.     "Non-mush commands are considered to be UNIX commands." },
  186.     { "verify", NULL,
  187.     "Verify to send, re-edit, or abort letter after editing." },
  188.     { "visual", "Visual editor:",
  189.     "Visual editor for messages (default = $editor or env VISUAL)."},
  190.     { "warning", NULL,
  191.     "Print warning messages for non-fatal errors." },
  192.     { "wrap", NULL,
  193.     "After referencing last message, message pointer wraps to start." },
  194.     { "wrapcolumn", "-Column to wrap [78]:",
  195.     "Column at which to wrap lines when composing messages." },
  196. };
  197.  
  198. #ifdef SUNTOOL
  199.  
  200. #define OPTIONS_PANEL_WIDTH    550
  201.  
  202. int set_value(), toggle_value(), help_opt();
  203.  
  204. Frame opts_frame;
  205. Panel opts_panel;
  206. Panel_item desc_msg;
  207. Panel_item file_text_item;
  208.  
  209. static void
  210. frame_done()
  211. {
  212. #ifdef SUN_4_0 /* SunOS 4.0+ */
  213.     window_set(opts_frame, WIN_SHOW, FALSE, NULL);
  214. #else /* SUN_4_0 */
  215.     /* not enough fd's to keep it lying around for SunOS 3.X */
  216.     window_destroy(opts_frame);
  217.     opts_frame = (Frame) 0;
  218. #endif /* SUN_4_0 */
  219. }
  220.  
  221. static void
  222. opts_help()
  223. {
  224.     help(0, "options", tool_help);
  225. }
  226.  
  227. static void
  228. opts_save_load(item)
  229. Panel_item item;
  230. {
  231.     int (*func)() = (int (*)())panel_get(item, PANEL_CLIENT_DATA);
  232.     int result;
  233.     char buf[MAXPATHLEN];
  234.     char *argv[3], *file = panel_get_value(file_text_item);
  235.  
  236.     if (!*file) {
  237.     result = (*func)(0, DUBL_NULL);
  238.     file = ".mushrc";
  239.     } else {
  240.     argv[1] = file;
  241.     argv[2] = NULL;
  242.     result = (*func)(2, argv);
  243.     }
  244.     switch (result) {
  245.     case 0:
  246.         sprintf(buf, "%s %s",
  247.         (func == source)? "Loaded options from" : "Saved options to",
  248.         file);
  249.     when -1:
  250.         sprintf(buf, "%s: %s", file, sys_errlist[errno]);
  251.     when -2:
  252.         sprintf(buf, "%s is a directory.", file);
  253.     when -3:
  254.         /* save_opts() returns -3 if user doesn't confirm overwrite */
  255.         strcpy(buf, "Save operation aborted.");
  256.     }
  257.     panel_set(desc_msg, PANEL_LABEL_STRING, buf, NULL);
  258. }
  259.  
  260. static void
  261. unset_opts()
  262. {
  263.     cmd_line("unset *", NULL);
  264. }
  265.  
  266. static void
  267. reset_opts()
  268. {
  269.     source(0, DUBL_NULL);
  270. }
  271.  
  272. /*
  273.  * Public routine which creates a subframe which contains two panels.
  274.  * The first contains options for loading and saving options from a
  275.  * file (text item) and so on... the second panel contains all the items
  276.  * which correspond to each mush variable that exists.
  277.  */
  278. void
  279. view_options()
  280. {
  281.     extern Notify_value fkey_interposer();
  282.     register char *p;
  283.     int count;
  284.  
  285.     if (opts_frame) {
  286.     window_set(opts_frame, WIN_SHOW, TRUE, NULL);
  287.     opts_panel_item(NULL);
  288.     return;
  289.     }
  290. #ifdef SUN_3_5
  291.     if (nopenfiles(0) < 3) {
  292.     ok_box("Too many frames; close one first!\n");
  293.     return;
  294.     }
  295. #endif /* SUN_3_5 */
  296.  
  297.     opts_frame = window_create(tool, FRAME,
  298.     FRAME_DONE_PROC,    frame_done,
  299.     FRAME_LABEL,        "Mush Options",
  300.     FRAME_NO_CONFIRM,    TRUE,
  301.     FRAME_SHOW_LABEL,    TRUE,
  302.     WIN_WIDTH,        OPTIONS_PANEL_WIDTH,
  303.     NULL);
  304.  
  305.     opts_panel = window_create(opts_frame, PANEL,
  306.     WIN_WIDTH,        OPTIONS_PANEL_WIDTH,
  307.     NULL);
  308.     (void) notify_interpose_event_func(opts_panel,
  309.     fkey_interposer, NOTIFY_SAFE);
  310.     panel_create_item(opts_panel, PANEL_BUTTON,
  311.     PANEL_LABEL_IMAGE,
  312.         panel_button_image(opts_panel, "Done", 4, mush_font),
  313.     PANEL_NOTIFY_PROC,    frame_done,
  314.     NULL);
  315.     panel_create_item(opts_panel, PANEL_BUTTON,
  316.     PANEL_LABEL_IMAGE,
  317.         panel_button_image(opts_panel, "Help", 4, mush_font),
  318.     PANEL_NOTIFY_PROC,    opts_help,
  319.     NULL);
  320.     panel_create_item(opts_panel, PANEL_BUTTON,
  321.     PANEL_LABEL_IMAGE,
  322.         panel_button_image(opts_panel, "Save", 4, mush_font),
  323.     PANEL_NOTIFY_PROC,    opts_save_load,
  324.     PANEL_CLIENT_DATA,    save_opts,
  325.     NULL);
  326.     panel_create_item(opts_panel, PANEL_BUTTON,
  327.     PANEL_LABEL_IMAGE,
  328.         panel_button_image(opts_panel, "Load", 4, mush_font),
  329.     PANEL_NOTIFY_PROC,    opts_save_load,
  330.     PANEL_CLIENT_DATA,    source,
  331.     NULL);
  332.     panel_create_item(opts_panel, PANEL_BUTTON,
  333.     PANEL_LABEL_IMAGE,
  334.         panel_button_image(opts_panel, "Clear", 5, mush_font),
  335.     PANEL_NOTIFY_PROC,    unset_opts,
  336.     NULL);
  337.     panel_create_item(opts_panel, PANEL_BUTTON,
  338.     PANEL_LABEL_IMAGE,
  339.         panel_button_image(opts_panel, "Restart", 7, mush_font),
  340.     PANEL_NOTIFY_PROC,    reset_opts,
  341.     NULL);
  342.     file_text_item = panel_create_item(opts_panel, PANEL_TEXT,
  343.     PANEL_LABEL_STRING,    "Save/Load File:",
  344.     PANEL_VALUE_DISPLAY_LENGTH, 30,
  345.     NULL);
  346.     desc_msg = panel_create_item(opts_panel, PANEL_MESSAGE,
  347.     PANEL_LABEL_STRING,    "Help Descriptions -- Click on Variable Name",
  348.     NULL);
  349.     window_fit_height(opts_panel);
  350.  
  351.     /* reuse opts_panel -- we don't need the other one */
  352.     opts_panel = window_create(opts_frame, PANEL,
  353.     WIN_BELOW,            opts_panel,
  354.     WIN_X,                0,
  355.     WIN_COLUMN_GAP,            120,
  356.     WIN_TOP_MARGIN,            10,
  357.     WIN_LEFT_MARGIN,        10,
  358.     WIN_WIDTH,            OPTIONS_PANEL_WIDTH,
  359.     PANEL_VERTICAL_SCROLLBAR,    scrollbar_create(NULL),
  360.     NULL);
  361.     (void) notify_interpose_event_func(opts_panel,
  362.     fkey_interposer, NOTIFY_SAFE);
  363.  
  364.     for (count = 0; count < ArraySize(viewopts); count++) {
  365.     panel_create_item(opts_panel, PANEL_MESSAGE,
  366.         PANEL_ITEM_X,    ATTR_COL(0),
  367.         PANEL_ITEM_Y,    ATTR_ROW(count),
  368.         PANEL_LABEL_STRING,    viewopts[count].v_opt,
  369.         PANEL_NOTIFY_PROC,    help_opt,
  370.         PANEL_CLIENT_DATA,    count,
  371.         NULL);
  372.  
  373.     if (!(p = viewopts[count].v_prompt) || *p == '-') {
  374.         if (p && *p)
  375.         p++;
  376.         viewopts[count].v_choice = panel_create_item(opts_panel,
  377.         PANEL_CHOICE,
  378.         PANEL_LABEL_IMAGE,    &cycle,
  379.         PANEL_LAYOUT,        PANEL_HORIZONTAL,
  380.         PANEL_CHOICE_STRINGS,    "False", "True", NULL,
  381.         PANEL_DISPLAY_LEVEL,    PANEL_CURRENT,
  382.         PANEL_ITEM_X,        ATTR_COL(1),
  383.         PANEL_ITEM_Y,        ATTR_ROW(count),
  384.         PANEL_NOTIFY_PROC,    toggle_value,
  385.         PANEL_CLIENT_DATA,    count,
  386.         NULL);
  387.     }
  388.     if (p) {
  389.         viewopts[count].v_text = panel_create_item(opts_panel, PANEL_TEXT,
  390.         PANEL_VALUE_DISPLAY_LENGTH,    10,
  391.         PANEL_VALUE_UNDERLINED,        TRUE,
  392.         PANEL_LABEL_STRING,        p,
  393.         PANEL_ITEM_X,            ATTR_COL(2),
  394.         PANEL_ITEM_Y,            ATTR_ROW(count),
  395.         PANEL_NOTIFY_PROC,        set_value,
  396.         PANEL_CLIENT_DATA,        count,
  397.         NULL);
  398.     }
  399.     }
  400.     /* set the panel items' values */
  401.     opts_panel_item(NULL);
  402.  
  403.     window_set(opts_panel,
  404.     WIN_HEIGHT,    400,
  405.     WIN_FIT_HEIGHT,    0,
  406.     NULL);
  407.     window_set(opts_frame, WIN_SHOW, TRUE, NULL);
  408. }
  409.  
  410. /*
  411.  * Sets the items in the panels to reflect that variable's value.
  412.  * If "var" is NULL, do it for all the items.
  413.  */
  414. void
  415. opts_panel_item(var)
  416. char *var;
  417. {
  418.     int count;
  419.     char *value;
  420.  
  421.     if (!opts_frame)
  422.     return;
  423.  
  424.     for (count = 0; count < ArraySize(viewopts); count++) {
  425.     if (var && strcmp(var, viewopts[count].v_opt))
  426.         continue;
  427.     value = do_set(set_options, viewopts[count].v_opt);
  428.  
  429.     if (!viewopts[count].v_prompt || *viewopts[count].v_prompt == '-')
  430.         panel_set_value(viewopts[count].v_choice, value != NULL);
  431.     if (viewopts[count].v_prompt)
  432.         panel_set_value(viewopts[count].v_text, value? value : "");
  433.     if (var)
  434.         break;
  435.     }
  436. }
  437.  
  438. /*
  439.  * Callback for choice items -- for variables that have boolean settings.
  440.  * CLIENT_DATA is the index in the viewopts array.
  441.  */
  442. static
  443. toggle_value(item, value)
  444. Panel_item item;
  445. int value;
  446. {
  447.     int count = (int) panel_get(item, PANEL_CLIENT_DATA);
  448.     char *p, *argv[4];
  449.     char *text_value = NULL;
  450.  
  451.     if (check_internal(viewopts[count].v_opt)) {
  452.     panel_set(desc_msg, PANEL_LABEL_STRING,
  453.         "This is an internal variable which cannot be changed.",
  454.         NULL);
  455.     return -1;
  456.     }
  457.  
  458.     if (p = viewopts[count].v_prompt) /* set equal */
  459.     text_value = panel_get_value(viewopts[count].v_text);
  460.  
  461.     if (!value)
  462.     (void) un_set(&set_options, viewopts[count].v_opt);
  463.     else {
  464.     /* Turn it on if it's entirely boolean or bool/str, but no str value */
  465.     if (!p || text_value && !*text_value) {
  466.         argv[0] = viewopts[count].v_opt; /* it's a boolean */
  467.         argv[1] = NULL;
  468.     } else {
  469.         /* string value -- determine the text from the typed in value */
  470.         argv[0] = viewopts[count].v_opt;
  471.         argv[1] = "=";
  472.         argv[2] = text_value;
  473.         argv[3] = NULL;
  474.     }
  475.     (void) add_option(&set_options, argv);
  476.     }
  477.  
  478.     if (!strcmp(viewopts[count].v_opt, "no_reverse") ||
  479.     !strcmp(viewopts[count].v_opt, "show_deleted"))
  480.     do_hdrs(0, DUBL_NULL, NULL);
  481.  
  482.     return 0;
  483. }
  484.  
  485. /* callback for text items -- set vars to the string typed. */
  486. static
  487. set_value(item, event)
  488. Panel_item item;
  489. Event *event;
  490. {
  491.     int count = (int)panel_get(item, PANEL_CLIENT_DATA);
  492.     char *p, *argv[4], *value;
  493.  
  494.     if (event_id(event) == '\t')
  495.     return (int) PANEL_NEXT;
  496.  
  497.     p = viewopts[count].v_prompt;
  498.     value = panel_get_value(item);
  499.  
  500.     if (check_internal(viewopts[count].v_opt)) {
  501.     panel_set(desc_msg, PANEL_LABEL_STRING,
  502.         "This is an internal variable which cannot be changed.",
  503.         NULL);
  504.     return (int) PANEL_NONE;
  505.     }
  506.  
  507.     /*
  508.      * You can "unset" string-only values by entering a blank string.
  509.      * If the "prompt" starts with a -, then you can only "unset" the
  510.      * variable by setting the associated choice item to false.
  511.      */
  512.     if (*p != '-' && !*value) {
  513.     (void) un_set(&set_options, viewopts[count].v_opt);
  514.     return (int) PANEL_NONE; /* do not advance caret */
  515.     }
  516.     /* Turn it on, but not to a value */
  517.     if (!*value) {
  518.     argv[0] = viewopts[count].v_opt; /* it's a boolean */
  519.     argv[1] = NULL;
  520.     } else {
  521.     /* string value -- determine the text from the typed in value */
  522.     argv[0] = viewopts[count].v_opt;
  523.     argv[1] = "=";
  524.     argv[2] = value;
  525.     argv[3] = NULL;
  526.     }
  527.  
  528.     (void) add_option(&set_options, argv);
  529.     if (p && *p == '-')
  530.     panel_set_value(viewopts[count].v_choice, TRUE);
  531.  
  532.     return (int) PANEL_NONE;
  533. }
  534.  
  535. /* when user clicks on variable label itself */
  536. static
  537. help_opt(item, event)
  538. Panel_item item;
  539. Event *event;
  540. {
  541.     int count = (int)panel_get(item, PANEL_CLIENT_DATA);
  542.  
  543.     panel_set(desc_msg,
  544.     PANEL_LABEL_STRING, viewopts[count].v_description,
  545.     NULL);
  546.     return 0;
  547. }
  548.  
  549. #endif /* SUNTOOL */
  550.  
  551. /*
  552.  * return a string describing a variable.
  553.  * parameters: count, str, buf.
  554.  * If str != NULL, check str against ALL variables
  555.  * in viewopts array.  The one that matches, set count to it and 
  556.  * print up all the stuff from the viewopts[count] into the buffer
  557.  * space in "buf" and return it.
  558.  */
  559. char *
  560. variable_stuff(count, str, buf)
  561. register char *str, *buf;
  562. {
  563.     if (str)
  564.     for (count = 0; count < ArraySize(viewopts); count++)
  565.         if (!strcmp(str, viewopts[count].v_opt))
  566.         break;
  567.     if (count >= ArraySize(viewopts)) {
  568.     (void) sprintf(buf, "%s: Not a default %s variable.",
  569.                str? str : itoa(count), prog_name);
  570.     return NULL;
  571.     }
  572.     return sprintf(buf, "%s: %s",
  573.     viewopts[count].v_opt, viewopts[count].v_description);
  574. }
  575.